#include "stdafx.h"
#include "Model.h"

#include "PhysicsSystem.h"

Model::Model(Ogre::SceneManager* sceneManager) {
	m_nextID = 0;
	m_goMap = new std::map<unsigned int, GameObject*>() ;
	m_sceneMgr = sceneManager;
	m_haveCamera = NULL;
}

Model::~Model() {
	//destroy all components!
	delete m_goMap;
	m_goMap = NULL;
}

GameObject* Model::getCameraGameObject() {
	return m_haveCamera;
}

void Model::update(float deltaTime) {
	//check all objects in collection to see if they are dead and need to be removed
	std::map<unsigned int,GameObject*>::iterator i;
	for(i=m_goMap->begin(); i != m_goMap->end(); ) {
		if(i->second->isDead()) {
			//If object is dead, remove it
			i->second->destroyAllMovableObjects(m_sceneMgr);
			delete i->second;
			i->second = NULL;
			m_goMap->erase(i++);
		}else {
			i->second->updateLogic();
			++i;
		}
	}
}

std::map<unsigned int, GameObject*>* Model::getGoMap() {
	return m_goMap;
}

GameObject* Model::getByID(unsigned int id) {
	if(m_goMap->find(id) != m_goMap->end()) {
		return (*m_goMap)[id];
	}else {
		return NULL;
	}
}

unsigned int Model::getNextID() {
	return m_nextID;
}

void Model::addGameObject(GameObject* gameObject, unsigned int id, float x, float y, float z) {
	//Create a scenenode for the gameobject
	Ogre::SceneNode* sceneNode = m_sceneMgr->getRootSceneNode()->createChildSceneNode();
	gameObject->setSceneNode(sceneNode);
	sceneNode->translate(x,y,z);
	//Let the gameobject create its visual component
	gameObject->createMovableObject(m_sceneMgr, id);

	//give the object's its ID
	gameObject->setID(id);

	//add to internal collection
	(*m_goMap)[id] = gameObject;
	
	//Update next available ID
	m_nextID = id + 1;

	gameObject->addedToModel();
	
	PlayerAvatar* pa = dynamic_cast<PlayerAvatar*>(gameObject);
	if (pa != 0) {
		m_playerAvatars.push_back(pa);
	}
}

bool Model::attachCamera(GameObject* object) {
	if (m_haveCamera != NULL) {

		m_haveCamera->whenCameraDetached();
		Ogre::MovableObject* camera = m_haveCamera->getCameraNode()->detachObject("PlayerCam");

		object->getCameraNode()->attachObject(camera);

		m_haveCamera = object;
		m_haveCamera->whenCameraAttached();
		return true;
	} else if (m_haveCamera == NULL) {
		return false;
	}
}

bool Model::attachCamera(GameObject* object, Ogre::Camera* cam) {
	if (m_haveCamera != NULL) {
		//Detach the camera from the object that it is currently attach to
		Ogre::MovableObject* camera = m_haveCamera->getSceneNode()->detachObject("PlayerCam");
		//Attach the camera to object
		object->getCameraNode()->attachObject(camera);
		m_haveCamera = object;
		return true;
	} else if (m_haveCamera == NULL) {
		object->getCameraNode()->attachObject(cam);
		m_haveCamera = object;
	}
}

PlayerAvatar* Model::getNextPlayerAvatar() {
	PlayerAvatar* tmp = m_playerAvatars.front();
	m_playerAvatars.pop_front();
	m_playerAvatars.push_back(tmp);
	return tmp;	
}

PlayerAvatar* Model::getPlayerAvatarByID(unsigned int id) {
	PlayerAvatar* tmp = NULL;
	std::list<PlayerAvatar*>::iterator it;
	for (it = m_playerAvatars.begin() ; it != m_playerAvatars.end() ; it++) {
		if ((*it)->getID() == id) {
			return (*it);
		}
	}
	return tmp;
}

Ogre::Vector3 Model::getCameraPosition() {
	return m_haveCamera->getPosition(m_haveCamera->getCameraNode());
}

Ogre::Quaternion Model::getCameraOrientation() {
	return m_haveCamera->getCameraNode()->getOrientation();
}